﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.ServiceModel;
using System.ServiceModel.Description;

namespace LostLib.Clouds
{
	[ServiceContract]
	public interface IServerNode
	{
		[OperationContract]
		CloudService Start(CloudServiceDescription service);

		[OperationContract]
		CloudService[] GetServices();
	}

	[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
	class ServerNode: IServerNode
	{
		Dictionary<CloudService, ServiceHost> hosts_;

		/// <summary>
		/// Starts new service on this node.
		/// </summary>
		/// <param name="service">Service to start.</param>
		/// <returns>CloudService object.</returns>
		public CloudService Start(string service)
		{
			Console.WriteLine("{0}\n{1}\n", service.Assembly, service.Type);
			Assembly assembly = Assembly.LoadFrom(service.Assembly);
			
			var type = assembly.GetType(service.Type);
			var iface = assembly.GetType(service.Interface);

			var uri = new Uri(CloudsMain.BaseAddress, type.Name);
			var host = new ServiceHost(type, uri);

			try
			{
				var endpoint = host.AddServiceEndpoint(iface, new WSHttpBinding(), "");

				var medatadaBehavior = new ServiceMetadataBehavior();
				medatadaBehavior.HttpGetEnabled = true;
				host.Description.Behaviors.Add(medatadaBehavior);

				host.Open();

				var svc = new CloudService {
					Uri = uri,
					Inteface = service.Interface,
				};

				Hosts.Add(svc, host);

				return svc;
			} catch (Exception error)
			{
				throw error;
			}
		}

		Dictionary<CloudService, ServiceHost> Hosts
		{
			get
			{
				if (hosts_ == null)
				{
					lock (this)
					{
						if (hosts_ == null)
							hosts_ = new Dictionary<CloudService, ServiceHost>();
					}
				}
				return hosts_;
			}
		}

		/// <summary>
		/// Lists all services running on this node.
		/// </summary>
		/// <returns>List of services</returns>
		public CloudService[] GetServices()
		{
			return Hosts.Keys.ToArray();
		}
	}
}
